#include "streamrecordermanager.h"
#include "streamrecordercontroller.h"

StreamRecorderManager::StreamRecorderManager(QObject* parent) : QObject(parent) { }

StreamRecorderManager::~StreamRecorderManager()
{
    terminateAll();
}

bool StreamRecorderManager::isRunning(int id) const
{
    for (auto c : std::as_const(controllers_)) {
        if (c->id() == id) {
            return true;
        }
    }
    return false;
}

int StreamRecorderManager::start(const StreamRecorderConfig& config)
{
    static int id = 0;

    StreamRecorderController* c = new StreamRecorderController(++id, this);
    controllers_.push_back(c);

    connect(c, &StreamRecorderController::positionChanged, this, [this](qint64 pos) {
        auto c = qobject_cast<StreamRecorderController*>(sender());
        Q_ASSERT(c);
        Q_EMIT positionChanged(c->id(), pos);
    });
    connect(c, &StreamRecorderController::qosMetrics, this, [this](double fps, double bitrate) {
        auto c = qobject_cast<StreamRecorderController*>(sender());
        Q_ASSERT(c);
        Q_EMIT qosMetrics(c->id(), fps, bitrate);
    });
    connect(c, &StreamRecorderController::finished, this,
            [this](const QString& filename, qint64 duration) {
                auto c = qobject_cast<StreamRecorderController*>(sender());
                Q_ASSERT(c);
                controllers_.removeOne(c);
                Q_EMIT finished(c->id(), filename, duration);
                c->deleteLater();
            });
    connect(c, &StreamRecorderController::errorOccurred, this,
            [this](int error, const QString& message) {
                Q_UNUSED(error)
                auto c = qobject_cast<StreamRecorderController*>(sender());
                Q_ASSERT(c);
                controllers_.removeOne(c);
                Q_EMIT errorOccurred(c->id(), message);
                c->deleteLater();
            });

    c->start(config);

    return id;
}

void StreamRecorderManager::stop(int id)
{
    for (auto c : std::as_const(controllers_)) {
        if (c->id() == id) {
            c->stop();
            break;
        }
    }
}

void StreamRecorderManager::stopAll()
{
    const auto cs = controllers_;
    for (auto c : cs) {
        c->stop();
    }
}

void StreamRecorderManager::terminate(int id)
{
    for (auto c : std::as_const(controllers_)) {
        if (c->id() == id) {
            disconnect(c, nullptr, this, nullptr);
            c->terminate();
            controllers_.removeOne(c);
            c->deleteLater();
            break;
        }
    }
}

void StreamRecorderManager::terminateAll()
{
    const auto cs = controllers_;
    for (auto c : cs) {
        disconnect(c, nullptr, this, nullptr);
        c->terminate();
        c->deleteLater();
    }
    controllers_.clear();
}
